from base_reposition import *
import numpy as np
import random

#  1. 环境设定模版，计算每个区域之间的距离矩阵

Region_info = [[(0, 0), (0, 200), (18, 0), (18, 200)], 
               [(120, 0), (56, 0), (120, 200), (56, 200)],
               [(121, 66), (300, 66), (121, 107), (300, 107)],
               [(396, 66), (300, 66), (300, 107), (396, 107)],
               [(396, 107), (396, 200), (331, 200), (331, 107)],
               [(18, 0), (56, 0), (18, 200), (56, 200)], 
               [(331, 107), (121, 107), (331, 139), (121, 139)],
               [(331, 139), (121, 139), (331, 200), (121, 200)],
               [(121, 0), (396, 0), (121, 66), (396, 66)],
               [(430, 0), (430, 200), (396, 0), (396, 200)]] 

def distance_matrix(NUM_REGION):
    # 创建一个全零矩阵，用于存储距离信息
    dist_matrix = np.zeros((NUM_REGION, NUM_REGION))

    # 遍历每对区域的组合
    for i in range(NUM_REGION):
        for j in range(i + 1, NUM_REGION):
            # 选择每个区域的第一个点作为代表

            # 计算欧氏距离并赋值给距离矩阵的对应位置
            dist_matrix[i, j] = euclidean_distance(Region_info[i], Region_info[j])
            dist_matrix[j, i] = dist_matrix[i, j]

    return dist_matrix

def euclidean_distance(region1, region2):
    # 计算两点之间的距离
    point1 = mean_point(region1)
    point2 = mean_point(region2)
    return np.sqrt((point2[0] - point1[0]) ** 2 + (point2[1] - point1[1]) ** 2)

def mean_point(region_points):
    # 返回中心点
    region_np = np.array(region_points)
    center = np.mean(region_np, axis=0)
    return center

dist_matrix = distance_matrix(10) # 每个区域之间的距离矩阵，根据实际情况更改

# 3. 异常检测初始化
class Outlier:
    def __init__(self, num_region, dist_matrix, number_source):
        self.num_region = num_region
        self.region_data = np.zeros((num_region * number_source))  # 每个区域当前step的信息
        self.region_data_all = []  # 存储所有的区域信息
        self.distances_region = dist_matrix
        self.number_source = number_source
        self.runner_step = 0
        self.outlier_info = None
        self.prev_outliers = None
        self.model_int = None  # 异常信息收集
        self.model_r = None# 异常信息收集

        self.is_anomalies = 0 # 是否异常 0没有异常 1有异常

    def step(self):
        self.region_data = np.zeros((self.num_region * self.number_source))

        #  执行核心步骤 ...
        if self.runner_step >= 10:
            self.update_region_data()  # 更新区域信息
        region_obser = self.generate_region_info() # 总的区域信息
        self.reposition_without(region_obser)
        self.runner_step += 1  # 更新step

    # 更新骑手在区域中的数据
    def update_region_data(self):
        # 更新其中的region_data中的棋手信息
        region_num = random.randint(0, 9) # 假设需要更换的区域编号为2 
        self.region_data[region_num * self.number_source] += 1 # 繁忙骑手数
        self.region_data[region_num * self.number_source + 1] += 1 # 空闲骑手数
        self.region_data[region_num * self.number_source + 2] += 1 # 繁忙骑手数
        self.region_data[region_num * self.number_source + 3] += 1 # 空闲骑手数

    def generate_region_info(self):
        # 反馈的实时信息，字典形式
        region_info = dict()
        distance = self.distances_region
        self.region_data_all.append(self.region_data)

        region_info["data"] = np.array(self.region_data_all)
        region_info["distance"] = distance
        region_info["number_region"] = self.num_region
        region_info["number_source"] = self.number_source
        region_info["detect_start"] = 0
        region_info["startTime"] = self.runner_step 
        region_info["endTime"] = len(self.region_data_all)
        
        return region_info
    
    def reposition_without(self, repo_observ):
        """只进行异常检测，不进行重调度

        Args:
            repo_observ (_type_): dict
        """

        self.is_anomalies = 0 #异常信息初始为0
      
        # 只进行异常检测 
        outliers, self.model_r, self.model_int = useOutlier_without(repo_observ, self.model_r, self.model_int)
        self.outlier_info = outliers[-1]
        # 更新 prev_outliers
        if self.prev_outliers is not None and np.array_equal(outliers, self.prev_outliers):
            print("No new anomalies detected.")
        else:
            print("New anomalies detected.")
            self.is_anomalies = 1
            self.prev_outliers = outliers

if __name__ == "__main__":
    rep = Outlier(10, dist_matrix, 5)

    for i in range(100):
        rep.step()